from math import log
from math import exp
import threading
import subprocess
import os
import shutil
import time

#trials = [1, 2]
#retransmitProtocols = ['0', '1']
#linkErrorRates = [0.0000005, 0.00000075, 0.000001, 0.00000125, 0.0000015, 0.00000175, 0.000002]
#windowSize = [2, 4, 8, 16, 32]
#segmentSize = [40000]

trials = [4, 5, 6]
retransmitProtocols = ['0', '1']
linkErrorRates = [0.0000005, 0.00000075, 0.000001, 0.00000125, 0.0000015, 0.00000175, 0.000002]
windowSize = [16]
segmentSize = [10000,20000,40000,80000,160000]
copyfile = '/tmp/simpleftp1'

class ServerThread (threading.Thread):
    def setup(self, configfile):
        self.configfile = configfile

    def run(self):
        self.p = subprocess.Popen(['./serv-exe', self.configfile], stdin=subprocess.PIPE)

    def cleanup(self):
        self.p.communicate('exit')

class ClientThread (threading.Thread):
    def setup(self, configfile):
        self.configfile = configfile

    def run(self):
        self.p = subprocess.Popen(['./cli-exe', self.configfile], stdin=subprocess.PIPE)

    def cleanup(self):
        self.p.kill()

class DNSThread (threading.Thread):
    def setup(self, filename, port, hostname):
        self.filename = filename
        self.port = port
        self.hostname = hostname

    def run(self):
        self.p = subprocess.Popen(['./simplednsd', self.filename, str(self.port), self.hostname])

    def cleanup(self):
        self.p.send_signal(2) #interrupt

class PHPThread (threading.Thread):
    def setup(self, filename, serverport, clientport):
        self.filename = filename
        self.serverport = serverport
        self.clientport = clientport

    def action(self):
        self.p = subprocess.call(['/usr/bin/php', 'exp.php', self.filename, str(self.serverport), str(self.clientport)])

def segmentErrorRateToBitErrorRate(rate, size):
    return 0 - exp(log(1 - rate) / (size * 8.0)) + 1

serverStartPort = 5000 
clientStartPort = 6000 
dnsStartPort = 7000 

def makeClientConfigFile(filename, port, proto, rate, window, segment):
    f = open(filename + ".client.config", 'w')
    f.write('clientListenPort %d \n' % port)
    f.write('statsFileName ' + filename + '.client.out\n')
    f.write('transportMSS %d\n' % segment)
    f.write('transportTimeout 200\n')
    f.write('retransmissionProtocol ' + proto + '\n')
    f.write('networkBitErrorRate %f\n' % rate)
    f.write('transportReceiveBuffer %d\n' % window)
    f.write('nsroot ' + filename + '.dns\n')
    f.close()

def makeServerConfigFile(filename, port, proto, rate, segment):
    f = open(filename + ".server.config", 'w')
    f.write('serverListenPort %d\n' % port)
    f.write('serverListenAddr 127.0.0.1\n')
    f.write('statsFileName ' + filename + '.server.out\n')
    f.write('transportMSS %d\n' % segment)
    f.write('transportTimeout 200\n')
    f.write('retransmissionProtocol ' + proto + '\n')
    f.write('networkBitErrorRate %f\n' % rate)
    f.write('nsroot ' + filename + '.dns\n')
    f.close()

def verifyFile(filepath):
    if not os.path.exists(filepath):
        random = open('/dev/random', 'r')
        testfile = open(filepath, 'w')
        for i in range((int) (10.0 * pow(2.0, 20.0))):
            testfile.write(random.read(1))
            
for trial in trials:       
    for proto in retransmitProtocols:
        for rate in linkErrorRates:
            for window in windowSize:
                for segment in segmentSize:
                    serverStartPort += 1
                    clientStartPort += 1
                    dnsStartPort += 1
                    filename = "%d_%s_%f_%d_%d" % (trial, proto, rate * 1000000, window, segment)
                    print 'experiment', filename
                    if(os.path.exists(filename + '.server.out')):
                        continue
                    makeServerConfigFile(filename, serverStartPort, proto, rate, segment)
                    makeClientConfigFile(filename, clientStartPort, proto, 0.0, window * segment, segment)
                    serverThread = ServerThread()
                    serverThread.setup(filename + ".server.config")
                    clientThread = ClientThread()
                    clientThread.setup(filename + ".client.config")
                    dnsThread = DNSThread()
                    dnsThread.setup(filename+".dns", dnsStartPort, "localhost")
                    phpThread = PHPThread()
                    phpThread.setup(copyfile, serverStartPort, clientStartPort)
                    verifyFile(copyfile)
                    dnsThread.start()
                    time.sleep(.1)
                    serverThread.start()
                    time.sleep(.1)
                    clientThread.start()
                    time.sleep(.1)
                    phpThread.action()
                    os.remove('/tmp/simpleftp1.copied')
                    clientThread.cleanup()
                    serverThread.cleanup()
                    dnsThread.cleanup()



__author__ = 'alex'
